class Sm < ActiveRecord::Base

  MAX_TRYING_COUNT = 10

  SEPARATOR = "/__mytusi_sm_split__/"

  belongs_to :user
  has_many :sm_statuses, :dependent => :destroy
  
  validates_presence_of :user_id,
    :content,
    :status
    
  def after_save
    SmStatus.create!(
      :sm_id => id,
      :user_id => user_id,
      :status => status,
      :exception => exception
    )
    UserSmsEmailsDailyStat.today_stat_by_user_id(user_id).add_sms_count! if sent?
  end

  # 高优先级
  def self.all_waitings_group_by_user(pri)
    all( :conditions => [
        'pri = ? and status = ? and trying_count <= ? and (created_at >= ? or created_at >= ?)',
        pri,
        'waiting',
        MAX_TRYING_COUNT,
        1.hours.ago,
        Date.today
      ]
    )
  end

  # 发送等待中的短信
  def self.sending_all_waitings_by_pri(pri)
    user_to_sms = all_waitings_group_by_user(pri).each_with_object({}) do |sm,user_to_sms|
      if sm.user.mobile?
        user_to_sms[sm.user] ||= []
        user_to_sms[sm.user] << sm
      end      
    end
    need_to_remind_users = all_waitings_group_by_user(pri).each_with_object([]) do |sm,users|
      if not sm.user.mobile?
        users << sm.user if not users.include?(sm.user)
        sm.trying_count = 100
        sm.exception! 'no supports maple20', :send_email => false
      end      
    end
    # 可发
    user_to_sms.keys.in_groups_of(20, false).each_with_object([]) do |users,threads|
      threads << Thread.new(users) do |users|
        users.each_with_object(user_to_sms) do |user,sms_hash|
          sms = sms_hash[user]
          def sms.add_sents_count!
            @sents_count ||= 0
            @sents_count += 1
          end
          def sms.sents_count
            @sents_count ||= 0
          end
          begin
            logger.debug "发送#{user.nick_name}的#{sms.size}条短信"            
            sms.each do |sm|
              sm.sending!
              user.send_sm_by_lite_fetion! sm.content
              sm.sent!
              sms.add_sents_count!
            end              
          rescue Exception => e
            # 异常
            logger.error "发送短信失败:#{e}"
            sms.each do |sm|
              sm.exception! e.to_s
            end
          end
          user.add_sms_count! :sms_count => sms.sents_count
        end   
      end
    end.each do |thread|
      thread.join
    end
    # 不可发
    need_to_remind_users.each do |user|
      UserMailer.deliver_fetion_need_verify user
    end
  end

  def sending!
    update_attributes! :status => 'sending',
      :trying_count => trying_count + 1    
  end

  def exception!(exception, options = { :send_email => true })
    if exception == 'execution expired' or exception == 'REQUEST_FAILED'
      update_attributes! :status => 'waiting',
        :exception => exception,
        :trying_count => 4
    else
      update_attributes! :status => 'waiting',
        :exception => exception
    end
    # 发送邮件    
    UserMailer.deliver_fetion_need_verify user if trying_count > Sm::MAX_TRYING_COUNT and options[:send_email]
  end
  
  def waiting!
    update_attributes! :status => 'waiting',
      :trying_count => 0
  end

  def sent!
    update_attributes! :status => 'sent'
  end

  def sending?
    status == 'sending'
  end

  def waiting?
    status == 'waiting'
  end

  def sent?
    status == 'sent'
  end
end
